package org.nViron.nvPlaces;

//~--- non-JDK imports --------------------------------------------------------

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.nViron.nvCommon.nvPosition;
import org.nViron.nvData.nvDataEntity;

/**
 * Basic algorithm that clusters data entities to form places
 * @author Roland Haring <p>
 * <script type="text/javascript" src="http://www.ohloh.net/p/376434/widgets/project_basic_stats.js"></script>
 */
public class nvBasicClusterer implements nvClusterer {
    private float maxDistanceForStacking;

    public nvBasicClusterer() {
        maxDistanceForStacking = 25.0f;
    }

    public void balancePlaces(HashMap places) {

        // TODO do some balancing?
    }

    public nvPlace findPlaceForEntity(HashMap places, nvDataEntity entity) {
        nvPlace foundPlace = null;
        double  minDist    = 10000000.0;

        for (Iterator i = places.values().iterator(); i.hasNext(); ) {
            nvPlace place = (nvPlace) i.next();
            double  dist  = place.getCenter().getDistance2d(entity.getPosition());

            // System.out.println("Distance: " + dist);
            if (dist < getMaxDistanceForStacking()) {
                if ((foundPlace == null) || ((foundPlace != null) && (dist < minDist))) {
                    if (foundPlace != null) {

                        // TODO check if we get here, cause this means, that we have potentially overlapping places (don't know yet if this is good or bad)
                    }

                    minDist    = dist;
                    foundPlace = place;
                }
            }
        }

        return foundPlace;
    }

    public nvPosition getCenter(ArrayList entities) {

        // simple geometeric implementation
        nvPosition center = new nvPosition();

        for (Iterator i = entities.iterator(); i.hasNext(); ) {
            nvDataEntity entity = (nvDataEntity) i.next();

            center.incLongitude(entity.getPosition().getLongitude());
            center.incLatitude(entity.getPosition().getLatitude());
            center.incAltitude(entity.getPosition().getAltitude());
        }

        center.mulLongitude(1.0 / entities.size());
        center.mulLatitude(1.0 / entities.size());
        center.mulAltitude(1.0f / entities.size());

        return center;
    }

    public float getMaxDistanceForStacking() {
        return maxDistanceForStacking;
    }

    public boolean keepCenter(nvPosition center, nvPosition newCenter) {
        float threshold = getMaxDistanceForStacking() / 10.0f;

        return center.getDistance2d(newCenter) < threshold;
    }

    public void setMaxDistanceForStacking(float dist) {
        this.maxDistanceForStacking = dist;
    }
}



